﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;


namespace Array
{
    class Program
    {
        static void Main(string[] args)
        {
            bool exitFlag = false;
            while (!exitFlag)
            {
                SortType sortType = (SortType)AskSortType();
                int arrayLenght = AskArrayLenght();
                int[] locArray = AskArrayType(arrayLenght);
                Console.WriteLine("Желаете ли вы посмотреть процесс сортирвки: <y/n>?");
                bool draw = AskToDraw();
                if (!draw)
                {
                    Console.Clear();
                    ChooseArrayTypeForDrawing(sortType, locArray);
                    // вызов отрисовки
                }
                else
                {
                    TimeSpan workSpan = Count(sortType, locArray);
                    Console.WriteLine("Время работы метода в милесекундах составило: {0} ", workSpan.TotalMilliseconds);
                }

                Console.WriteLine("Желаете продолжить: <y/n>?");
                exitFlag = AskForExit();
                Console.WriteLine();

            }
        }
        public static void DrawArrayMOD(int[] locArray, int MIN, int MAX)
        {
            int yMin = MIN;
            int yMax = MAX;
            int xMax = locArray.Length;
            int j = 0;
            for (int i = 0; i <= yMax; i++)
            {
                if (locArray[j] == i)
                {
                    Console.SetCursorPosition(j, yMax - locArray[j]);
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.Write(".");
                    Console.ResetColor();
                    j++;
                    i = 0;
                }
                if (j == locArray.Length)
                    break;
            }
        }//Отрисовка
        public static bool AskForExit()
        {
            bool exitFlag = true;
            char exit = ' ';
            bool inputIsCorrect = false;
            while (!inputIsCorrect)
            {
                try
                {
                    exit = Char.Parse(Console.ReadLine());
                    if (exit == 'y' || exit == 'n')
                        inputIsCorrect = true;
                    else
                        throw new ArgumentException();
                }
                catch
                {
                    Console.WriteLine("Неправильный ввод");
                    Console.WriteLine("Желаете продолжить: <y/n>?");
                }
            }
            if (exit == 'y')
                exitFlag = false;
            else
                exitFlag = true;
            return exitFlag;
        }
        public static bool AskToDraw()
        {
            bool exitFlag = true;
            char exit = ' ';
            bool inputIsCorrect = false;
            while (!inputIsCorrect)
            {
                try
                {
                    exit = Char.Parse(Console.ReadLine());
                    if (exit == 'y' || exit == 'n')
                        inputIsCorrect = true;
                    else
                        throw new ArgumentException();
                }
                catch
                {
                    Console.WriteLine("Неправильный ввод");
                    Console.WriteLine("Желаете ли вы посмотреть процесс сортирвки: <y/n>?");
                }
            }
            if (exit == 'y')
                exitFlag = false;
            else
                exitFlag = true;
            return exitFlag;
        }
        public static int AskSortType()
        {
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine("                  Выберите метод сортировки.\n" +
                              "\n \tМетод 'Пузырек' \tнажми - '1'\n \tМетод 'Подбором' \tнажми - '2'\n \tМетод 'Перемещения' \tнажми - '3'");
            Console.ResetColor();
            int sortType = ReadIntFromConsole(1, 3);
            return sortType;
        }//Определяем тип сортировки
        public static int AskArrayLenght()
        {
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine("\t\tОпределите длинну массива для эксперимента от 1 до 1000.");
            Console.ResetColor();
            int arrayLenght = ReadIntFromConsole(1, 1000);
            return arrayLenght;
        }// Определяем длинну массива
        public static int[] AskArrayType(int arrayLenght)
        {

            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine("\n\t\t  Выбирите тип массива.\n\t'Отсортированный' \tнажми - '1'\n\t'Случайный' \t\tнажми - '2'\n\t'Реверсный' \t\tнажми - '3' ");
            Console.ResetColor();
            int[] locArray = { };
            int arrayType = ReadIntFromConsole(1, 3);
            switch (arrayType)
            {
                case 1:
                    locArray = CreateRandomIntArray(arrayLenght);
                    break;
                case 2:
                    locArray = CreateIntArray(arrayLenght);
                    break;
                case 3:
                    locArray = CreateReverseIntArray(arrayLenght);
                    break;
            }
            return locArray;
        }//Создает выбранный тип массива
        public static TimeSpan Count(SortType sortType, int[] locArray)//время сортировки
        {
            DateTime start = DateTime.Now;
            DateTime currentDate = new DateTime(); ;
            TimeSpan span = new TimeSpan();
            int length1 = locArray.Length;
            switch (sortType)
            {
                case SortType.BubbleSort:
                    BubbleSort(locArray);
                    currentDate = DateTime.Now;
                    span = currentDate - start;
                    break;
                case SortType.SelectionSort:

                    SelectionSort(locArray);
                    currentDate = DateTime.Now;
                    span = currentDate - start;
                    break;
                case SortType.ShakerSort:
                    ShakerSort(locArray);
                    currentDate = DateTime.Now;
                    span = currentDate - start;
                    break;
            }
            return span;
        }
        public static void ChooseArrayTypeForDrawing(SortType sortType, int[] locArray)
        {
            int length = locArray.Length;
            int MAX = locArray[0], MIN = locArray[0];
            for (int i = 0; i < length; i++)
            {
                if (MIN > locArray[i])
                    MIN = locArray[i];
                if (MAX < locArray[i])
                    MAX = locArray[i];
            }
            switch (sortType)
            {
                case SortType.BubbleSort:
                    Console.SetWindowPosition(0, 0);
                    Console.SetWindowSize(Console.LargestWindowWidth, Console.LargestWindowHeight);

                    BubbleSort(locArray, MIN, MAX);
                    Console.SetCursorPosition(0, MAX);
                    Console.WriteLine("Массив отсортирован, консоль будет очищена через 5 секунд");
                    Thread.Sleep(5000);
                    Console.Clear();
                    break;
                case SortType.SelectionSort:
                    Console.SetWindowPosition(0, 0);
                    Console.SetWindowSize(Console.LargestWindowWidth, Console.LargestWindowHeight);
                    SelectionSort(locArray, MIN, MAX);
                    Console.SetCursorPosition(0, MAX);
                    Console.WriteLine("Массив отсортирован, консоль будет очищена через 5 секунд");
                    Thread.Sleep(5000);
                    Console.Clear();
                    break;
                case SortType.ShakerSort:
                    Console.SetWindowPosition(0, 0);
                    Console.SetWindowSize(Console.LargestWindowWidth, Console.LargestWindowHeight);
                    ShaykerSort(locArray, MIN, MAX);
                    Console.SetCursorPosition(0, MAX);
                    Console.WriteLine("Массив отсортирован, консоль будет очищена через 5 секунд");
                    Thread.Sleep(5000);
                    Console.Clear();
                    break;

            }
        }//Определяем тип сортировки
        public static int ReadIntFromConsole()
        {
            int result = 0;
            bool inputFail = true;
            while (inputFail)
            {
                try
                {
                    result = int.Parse(Console.ReadLine());
                    inputFail = false;
                }
                catch
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("Не правильный формат ввода.");
                    Console.ResetColor();
                }
            }
            return result;
        }
        public static int ReadIntFromConsole(int minValue, int maxValue)
        {
            int suka = 0;
            bool flag = true;

            while (flag)
            {
                int res = ReadIntFromConsole();
                if (res >= minValue && res <= maxValue)
                {
                    suka = res;
                    flag = false;
                }
                else
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("Не влез в диапазон Заданного значения!!!\n\a Диапазон значений от {0} до {1}", minValue, maxValue);
                    Console.ResetColor();
                }
            }
            return suka;

        }
        public static void PrintIntArray(int[] locArray)
        {
            int length = locArray.Length;
            for (int i = 0; i < length; i++)
            {
                Console.Write(locArray[i] + "  ");
            }
        }
        public static int[] CreateIntArray(int number)
        {
            int[] locArray = new int[number];
            for (int i = 0; i < number; i++)
            {
                locArray[i] = i + 1;
            }
            return locArray;
        }//          0..n
        public static int[] CreateReverseIntArray(int number)
        {
            int[] locArray = new int[number];
            int j = 0;
            for (int i = number; i > 0; i--)
            {
                locArray[j] = number;
                number--;
                j++;
            }
            return locArray;
        }//   n..o
        public static int[] CreateRandomIntArray(int number)
        {
            int[] locArray = new int[number];
            Random rand = new Random();
            for (int i = 0; i < number; i++)
            {
                locArray[i] = rand.Next(0, 50);
            }
            return locArray;
        }//    Rendom
        public static void BubbleSort(int[] input, int MIN, int MAX)
        {
            int temp;
            for (int i = 0; i < input.Length - 1; i++)
            {
                for (int j = 0; j < input.Length - i - 1; j++)
                {
                    if (input[j] > input[j + 1])
                    {
                        temp = input[j];
                        input[j] = input[j + 1];
                        input[j + 1] = temp;
                        Console.Clear();
                        DrawArrayMOD(input, MIN, MAX);
                        Thread.Sleep(2);
                    }
                }
            }
        }//Сортировка пузырьком.1
        public static void BubbleSort(int[] input)
        {
            int temp;
            for (int i = 0; i < input.Length - 1; i++)
            {
                for (int j = 0; j < input.Length - i - 1; j++)
                {
                    if (input[j] > input[j + 1])
                    {
                        temp = input[j];
                        input[j] = input[j + 1];
                        input[j + 1] = temp;
                    }
                }
            }
        }                //Сортировка пузырьком.1
        public static void SelectionSort(int[] locArray)
        {
            for (int i = 0; i < locArray.Length; i++)
            {
                int min = i; int x = locArray[i];
                for (int j = i + 1; j < locArray.Length; j++)
                {
                    if (locArray[j] < x)
                    {
                        min = j; x = locArray[j];
                    }
                }
                locArray[min] = locArray[i];
                locArray[i] = x;
            }
        }                 //Сортировка подбором.2
        public static void SelectionSort(int[] locArray, int MIN, int MAX)
        {
            for (int i = 0; i < locArray.Length; i++)
            {
                int min = i; int x = locArray[i];
                for (int j = i + 1; j < locArray.Length; j++)
                {
                    if (locArray[j] < x)
                    {
                        min = j; x = locArray[j];
                        Console.Clear();
                        DrawArrayMOD(locArray, MIN, MAX);
                        Thread.Sleep(2);
                    }
                }
                locArray[min] = locArray[i];
                locArray[i] = x;
                Console.Clear();
                DrawArrayMOD(locArray, MIN, MAX);
                Thread.Sleep(2);
            }
        }//Сортировка подбором.2
        public static void ShakerSort(int[] input)
        {
            int beg, end;
            int count = 0;

            for (int i = 0; i < input.Length / 2; i++)
            {
                beg = 0;
                end = input.Length - 1;
                do
                {
                    count += 2;
                    /* идем спереди*/
                    if (input[beg] > input[beg + 1])
                        SwapArrItems(input, beg, beg + 1);
                    beg++;

                    /*идем сзади*/
                    if (input[end - 1] > input[end])
                        SwapArrItems(input, end - 1, end);
                    end--;
                }
                while (beg <= end);
            }
        }                      //Сортировка метод перемещением.3
        public static void ShaykerSort(int[] locArray, int MIN, int MAX)
        {
            int l2 = 1, r2 = locArray.Length - 1;
            int k2 = locArray.Length - 1, tmp2;
            do
            {
                for (int i = r2; i > 0; i--)
                {
                    if (locArray[i - 1] > locArray[i])
                    {
                        tmp2 = locArray[i - 1];
                        locArray[i - 1] = locArray[i];
                        locArray[i] = tmp2;
                        k2 = i;
                        Console.Clear();
                        DrawArrayMOD(locArray, MIN, MAX);
                        Thread.Sleep(30);
                    }
                }
                l2 = k2 + 1;
                for (int i = 1; i <= r2; i++)
                {
                    if (locArray[i - 1] > locArray[i])
                    {
                        tmp2 = locArray[i - 1];
                        locArray[i - 1] = locArray[i];
                        locArray[i] = tmp2;
                        k2 = i;
                        Console.Clear();
                        DrawArrayMOD(locArray, MIN, MAX);
                        Thread.Sleep(30);
                    }
                }
                r2 = k2 - 1;

            }
            while (l2 < r2);
            Console.Clear();
            DrawArrayMOD(locArray, MIN, MAX);
            Thread.Sleep(30);
        }//Сортировка метод перемещением.3
        public static void SwapArrItems(int[] mas, int a, int b)
        {
            mas[a] = mas[a] + mas[b];
            mas[b] = mas[a] - mas[b];
            mas[a] = mas[a] - mas[b];
        }
        public enum SortType
        {
            BubbleSort = 1,
            SelectionSort = 2,
            ShakerSort = 3
        };
    }
}
